/*
 * @Descripttion: 
 * @Author: zhangchong zc16607@gmail.com
 * @Date: 2023-02-27 16:08:44
 * @LastEditors: zhangchong zc16607@gmail.com
 * @LastEditTime: 2023-02-28 11:08:00
 */
// 实例化的时候传入任务并发执行数量
class TaskQueue {
  constructor(concurrency = 1) {
    this.taskArr = [] // 任务队列
    this.concurrency = concurrency // 即将启动的并发数量
    this.runningNum = 0  // 启动中的并发数
  }

  startTask() {
    this.isRunning = true     // 标记正在运行队列中的任务
    for (let i = 0; i < this.concurrency; i++) {  // 启动并发任务
      let current = this.taskArr.shift()
      if (current) {
        // console.log('并发执行数：',i, current)
        this.runningNum++
        current()
      } else {
        // console.log('任务队列暂无任务！')
      }
    }
  }

  addTask(asyncFunc, callback) {
    let promiseTask = () => {
      return asyncFunc().then((res) => {
        callback(res)                     // 用户的异步执行完成回调
        let next = this.taskArr.shift()
        if (next) {
          next()                          // 每个任务都需要调用下一个任务
        } else {                            // 没有任务则将状态标记为未运行
          this.runningNum--
          if (this.taskArr.length === 0 && this.runningNum === 0) {
            this.isRunning = false
            this.taskResolve && this.taskResolve(true)        // 任务完成
          }
        }
      })
    }
    this.taskArr.push(promiseTask)

    if (!this.isRunning) {
      this.isRunning = true                // 启动标识不能是异步
      this.taskStatusPromise = new Promise((resolve, reject) => { // 队列状态恢复到运行中
        this.taskResolve = resolve
      })
      queueMicrotask(() => {               // 也可以用setTimeout
        this.startTask()                   // 启动任务很关键，必须是异步！！！
      })                                   // 目的是让taskArr添加多条任务之后再启动
    }                                      // 这样启动并发任务时，shift()才能取到任务
  }

  // 获取任务队列是否完成
  getQueueComplete() {
    if (!this.taskResolve) return true // 如果只实例化，但是没有添加任务，此时获取状态应该为完成
    return this.taskStatusPromise
  }
}

module.exports = TaskQueue